#define ENABLE_HSV_CONVERSION  	// Enables HSV Conversion. Required for color controls below.
#define ENABLE_SATURATION_ADJUSTMENT	// Enables color saturation control for the entire scene.
#define ENABLE_INTENSITY_ADJUSTMENT  // Enables brightness control for the entire scene.
#define ENABLE_HUE_ADJUSTMENT    	// Enables hue control for the entire scene.
#define ENABLE_COLOR_EQUALIZER    // Enables the Color Equalizer system for advanced tweaking.

//#define ENABLE_POW_CURVE    // Enables power curve controls.

// Color Saturation Variables
float	EColorSaturationMod=0.0;  // Adds to the overall color saturation. Range: -1 to 1. Default: 0.0
float	EColorSaturationMult=1.0;  // Multiplies the color saturation. Range: 0.0 (greyscale) to ???. Default: 1.0
float	EColorSaturationPow=1.0;  // Curves the color saturation. Range: 0.0 to ???. Default: 1.0

// Color Intensity Variables
float   EColorIntensityMod=0.0;  	// Adds to the overall brightness. Range: -1 to 1. Default: 0.0
float   EColorIntensityMult=1.0;  // Multiplies the color intensity. Range: 0.0 (black) to ???. Default: 1.0
float   EColorIntensityPow=1.0;  	// Curves the color intensity. Range: 0.0 to ???. Default: 1.0

// Color Hue Variables
float   EColorHueMod=0.0;    // Adds to the overall color hue (color shifting). Range: -1 to 1. Default: 0.0
float   EColorHueMult=1.0;    // Multiplies the color hue (color shifting). Range: 0.0 to ???. Default: 1.0
float	EColorHuePow=1.0;    // Curves the color hue. Range: 0.0 to ???. Default: 1.0.

// Color Equalizer Variables
// Adjust modifier to specific saturations. Range: -??? to ???. Default: 0.0
float	SaturationModRed = 0.0;
float	SaturationModOrange = 0.0;
float	SaturationModYellow = 0.0;
float	SaturationModGreen = 0.0;
float	SaturationModCyan = 0.0;
float	SaturationModBlue = 0.0;
float	SaturationModMagenta = 0.0;

// Adjust multiplier to specific saturations. Range: 0.0 to ???. Default: 0.0
float	SaturationMultRed = 0.1;
float	SaturationMultOrange = -0.2;
float	SaturationMultYellow = 0.0;
float	SaturationMultGreen = 0.2;
float	SaturationMultCyan = -0.1;
float	SaturationMultBlue = 0.0;
float	SaturationMultMagenta = 0.1;

// Adjust curve of specific saturations. Range: -1.0 to ???. Default: 0.0
float	SaturationPowRed = 0.0;
float	SaturationPowOrange = 0.0;
float	SaturationPowYellow = 0.0;
float	SaturationPowGreen = 0.0;
float	SaturationPowCyan = 0.0;
float	SaturationPowBlue = 0.0;
float	SaturationPowMagenta = 0.0;

//////////////////////////////////////////////
// DO NOT MODIFY ANYTHING BELOW THIS LINE,  //
// UNLESS YOU KNOW HLSL SHADER PROGRAMMING. //
//////////////////////////////////////////////

// List of floating point values for hues, used in equalizer.
float	HueRed = 0.0;
float	HueOrange = 0.08333333;
float	HueYellow = 0.16666667;
float	HueGreen = 0.33333333;
float	HueCyan = 0.5;
float	HueBlue = 0.66666667;
float	HueMagenta = 0.83333333;
float	HueRed2 = 1.0;

float	HueSkin = 0.07;
float	HueSky = 0.58;


float ColorEqualizerMult(in float H)
{
float SMult = 1.0;
SMult += SaturationMultRed * ( 1.0 - min( 1.0, abs( ( HueRed - H ) / ( HueRed - HueOrange ) ) ) );
SMult += SaturationMultOrange * ( 1.0 - min( 1.0, abs( ( HueOrange - H ) / ( HueOrange - HueYellow ) ) ) );
SMult += SaturationMultYellow * ( 1.0 - min( 1.0, abs( ( HueYellow - H ) / ( HueYellow - HueGreen ) ) ) );
SMult += SaturationMultGreen * ( 1.0 - min( 1.0, abs( ( HueGreen - H ) / ( HueGreen - HueYellow ) ) ) );
SMult += SaturationMultCyan * ( 1.0 - min( 1.0, abs( ( HueCyan - H ) / ( HueCyan - HueGreen ) ) ) );
SMult += SaturationMultBlue * ( 1.0 - min( 1.0, abs( ( HueBlue - H ) / ( HueBlue - HueCyan ) ) ) );
SMult += SaturationMultMagenta * ( 1.0 - min( 1.0, abs( ( HueMagenta - H ) / ( HueMagenta - HueBlue ) ) ) );
SMult += SaturationMultRed * ( 1.0 - min( 1.0, abs( ( HueRed2 - H ) / ( HueRed2 - HueMagenta ) ) ) );
return SMult;
}

float ColorEqualizerMod(in float H)	
{
float SMod = 0.0;
SMod += SaturationModRed * ( 1.0 - min( 1.0, abs( ( HueRed - H ) / ( HueRed - HueOrange ) ) ) );
SMod += SaturationModOrange * ( 1.0 - min( 1.0, abs( ( HueOrange - H ) / ( HueOrange - HueYellow ) ) ) );
SMod += SaturationModYellow * ( 1.0 - min( 1.0, abs( ( HueYellow - H ) / ( HueYellow - HueGreen ) ) ) );
SMod += SaturationModGreen * ( 1.0 - min( 1.0, abs( ( HueGreen - H ) / ( HueGreen - HueYellow ) ) ) );
SMod += SaturationModCyan * ( 1.0 - min( 1.0, abs( ( HueCyan - H ) / ( HueCyan - HueGreen ) ) ) );
SMod += SaturationModBlue * ( 1.0 - min( 1.0, abs( ( HueBlue - H ) / ( HueBlue - HueCyan ) ) ) );
SMod += SaturationModMagenta * ( 1.0 - min( 1.0, abs( ( HueMagenta - H ) / ( HueMagenta - HueBlue ) ) ) );
SMod += SaturationModRed * ( 1.0 - min( 1.0, abs( ( HueRed2 - H ) / ( HueRed2 - HueMagenta ) ) ) );
return SMod;
}

float ColorEqualizerPow(in float H)	
{
float SPow = 1.0;
SPow += SaturationPowRed * ( 1.0 - min( 1.0, abs( ( HueRed - H ) / ( HueRed - HueOrange ) ) ) );
SPow += SaturationPowOrange * ( 1.0 - min( 1.0, abs( ( HueOrange - H ) / ( HueOrange - HueYellow ) ) ) );
SPow += SaturationPowYellow * ( 1.0 - min( 1.0, abs( ( HueYellow - H ) / ( HueYellow - HueGreen ) ) ) );
SPow += SaturationPowGreen * ( 1.0 - min( 1.0, abs( ( HueGreen - H ) / ( HueGreen - HueYellow ) ) ) );
SPow += SaturationPowCyan * ( 1.0 - min( 1.0, abs( ( HueCyan - H ) / ( HueCyan - HueGreen ) ) ) );
SPow += SaturationPowBlue * ( 1.0 - min( 1.0, abs( ( HueBlue - H ) / ( HueBlue - HueCyan ) ) ) );
SPow += SaturationPowMagenta * ( 1.0 - min( 1.0, abs( ( HueMagenta - H ) / ( HueMagenta - HueBlue ) ) ) );
SPow += SaturationPowRed * ( 1.0 - min( 1.0, abs( ( HueRed2 - H ) / ( HueRed2 - HueMagenta ) ) ) );
return SPow;
}

float3 HUEtoRGB(in float H)
{
   float R = abs(H * 6.0 - 3.0) - 1.0;
   float G = 2.0 - abs(H * 6.0 - 2.0);
   float B = 2.0 - abs(H * 6.0 - 4.0);
   return saturate(float3(R,G,B));
}

float RGBCVtoHUE(in float3 RGB, in float C, in float V)
{
     float3 Delta = (V - RGB) / C;
     Delta.rgb -= Delta.brg;
     Delta.rgb += float3(2.0,4.0,6.0);
     Delta.brg = step(V, RGB) * Delta.brg;
     float H;
     H = max(Delta.r, max(Delta.g, Delta.b));
     return frac(H / 6.0);
}

float3 HSVtoRGB(in float3 HSV)
{
   float3 RGB = HUEtoRGB(HSV.x);
   return ((RGB - 1) * HSV.y + 1) * HSV.z;
}
 
float3 RGBtoHSV(in float3 RGB)
{
   float3 HSV = 0.0;
   HSV.z = max(RGB.r, max(RGB.g, RGB.b));
   float M = min(RGB.r, min(RGB.g, RGB.b));
   float C = HSV.z - M;
   if (C != 0.0)
   {
     HSV.x = RGBCVtoHUE(RGB, C, HSV.z);
     HSV.y = C / HSV.z;
   }
   return HSV;
}





//global variables, already set before executing this code
float ScreenSize : register(c218); //width of the display resolution (1024 f.e.)
float ScreenScaleY : register(c219); //screen proportions (1.333 for 1024/768)

//textures
texture2D texColor;
texture2D texNoise;
texture2D texs4;

sampler2D SamplerColor = sampler_state
{
Texture   = <texColor>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = NONE;//NONE;
AddressU  = Clamp;
AddressV  = Clamp;
SRGBTexture=FALSE;
MaxMipLevel=0;
MipMapLodBias=0;
};

sampler2D SamplerNoise = sampler_state
{
Texture   = <texNoise>;
MinFilter = POINT;
MagFilter = POINT;
MipFilter = NONE;//NONE;
AddressU  = Wrap;
AddressV  = Wrap;
SRGBTexture=FALSE;
MaxMipLevel=0;
MipMapLodBias=0;
};

sampler2D _s4 = sampler_state
{
Texture   = <texs4>;
MinFilter = LINEAR;//
MagFilter = LINEAR;//
MipFilter = NONE;//LINEAR;
AddressU  = Clamp;
AddressV  = Clamp;
SRGBTexture=FALSE;
MaxMipLevel=0;
MipMapLodBias=0;
};

struct VS_OUTPUT_POST {
float4 vpos  : POSITION;
float2 txcoord : TEXCOORD0;
};

struct VS_INPUT_POST {
float3 pos  : POSITION;
float2 txcoord : TEXCOORD0;
};

VS_OUTPUT_POST VS_PostProcess(VS_INPUT_POST IN)
{
VS_OUTPUT_POST OUT;

float4 pos=float4(IN.pos.x,IN.pos.y,IN.pos.z,1.0);

OUT.vpos=pos;
OUT.txcoord.xy=IN.txcoord.xy;

return OUT;
}

float4 mainPS(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
   float4 color = tex2D(SamplerColor, IN.txcoord.xy);


#ifdef ENABLE_HSV_CONVERSION
float3 hsvcolor = RGBtoHSV( color.xyz );

#ifdef ENABLE_POW_CURVE
#ifdef ENABLE_HUE_ADJUSTMENT
hsvcolor.x = EColorHueMod + ( EColorHueMult * pow( hsvcolor.x, EColorHuePow ) );
#endif
#ifdef ENABLE_SATURATION_ADJUSTMENT
hsvcolor.y = EColorSaturationMod + ( EColorSaturationMult * pow( hsvcolor.y, EColorSaturationPow ) );
#endif
#ifdef ENABLE_INTENSITY_ADJUSTMENT
hsvcolor.z = EColorIntensityMod + ( EColorIntensityMult * pow( hsvcolor.z, EColorIntensityPow ) );
#endif
#ifdef ENABLE_COLOR_EQUALIZER
hsvcolor.y = ColorEqualizerMod( hsvcolor.x ) + ( ColorEqualizerMult( hsvcolor.x ) * pow( hsvcolor.y, ColorEqualizerPow( hsvcolor.x ) ) );
#endif
#endif

#ifndef ENABLE_POW_CURVE
#ifdef ENABLE_HUE_ADJUSTMENT
hsvcolor.x = EColorHueMod + ( EColorHueMult * hsvcolor.x );
#endif
#ifdef ENABLE_SATURATION_ADJUSTMENT
hsvcolor.y = EColorSaturationMod + ( EColorSaturationMult * hsvcolor.y );
#endif
#ifdef ENABLE_INTENSITY_ADJUSTMENT
hsvcolor.z = EColorIntensityMod + ( EColorIntensityMult * hsvcolor.z );
#endif
#ifdef ENABLE_COLOR_EQUALIZER
hsvcolor.y = ColorEqualizerMod( hsvcolor.x ) + ( ColorEqualizerMult( hsvcolor.x ) * hsvcolor.y );
#endif
#endif

hsvcolor.y = max( hsvcolor.y, 0.0 );
hsvcolor.z = max( hsvcolor.z, 0.0 );
color.xyz = HSVtoRGB( hsvcolor );
#endif


return color;
}



technique PostProcess
{
pass P0
{

 VertexShader = compile vs_3_0 VS_PostProcess();
 PixelShader  = compile ps_3_0 mainPS();

 DitherEnable=FALSE;
 ZEnable=FALSE;
 CullMode=NONE;
 ALPHATESTENABLE=FALSE;
 SEPARATEALPHABLENDENABLE=FALSE;
 AlphaBlendEnable=FALSE;
 StencilEnable=FALSE;
 FogEnable=FALSE;
 SRGBWRITEENABLE=FALSE;
}

}